/*	--- 原型 --- 

# 用【原型实例】指定【创建对象的种类】，并且通过【拷贝】这些【原型】创建【新的对象】。

=========================================================


【原型模式】，即【Prototype】，是指创建新对象的时候，根据【现有的一个原型】来创建。

我们举个例子：
  如果我们已经有了一个String[]数组，想再创建一个一模一样的String[]数组，怎么写？

  实际上创建过程很简单，就是把【现有数组的元素】复制到【新数组】。如

  果我们把【这个创建过程】【封装】一下，就成了【原型模式】。

用代码实现如下： */

// 原型
String[] original = { "Apple", "Pear", "Banana" };

// 新对象
String[] copy = Arrays.copyOf(original, original.length);



/*
Q: 对于普通类，我们如何实现原型拷贝？
A: Java的Object提供了一个clone()方法，它的意图就是【复制】一个【新的对象】出来，我们需要实现【一个Cloneable接口】来标识【一个对象】是“可复制”的： */
public class Student implements Cloneable {
	private int id;
	private String name;
	private int score;

	// 复制新对象, 并返回
	public Object clone() {
		Student std = new Student();

		std.id = this.id;
		std.name = this.name;
		std.score = this.score;

		return std;
	}
}


/*
使用的时候，因为clone()的方法签名是定义在Object中，返回类型也是Object，所以要强制转型，比较麻烦： */
Student std1 = new Student();
std1.setId(123);
std1.setName("Bob");
std1.setScore(88);

// 复制新对象
Student std2 = (Student) std1.clone();
System.out.println(std1);
System.out.println(std2);
System.out.println(std3);
System.out.println(std == std2); // false, 地址不同


/*
实际上，使用原型模式更好的方式是定义一个copy()方法，返回明确的类型：*/
public class Student {
	private int id;
	private String name;
	private int score;

	public Student copy() {  // return type=Student
		Student std = new Student();

		std.id = this.id;
		std.name = this.name;
		std.score = this.score;

		return std;
	}
}


/*
【原型模式】应用不是很广泛，因为很多【实例】会持有类似【文件、Socket】这样的资源，而这些资源是【无法复制】给另一个对象【共享】的，
只有【存储简单类型 的 “值”对象】可以复制。


=======================================================


#  练习

给Student类增加clone()方法。 */

public class Student {
	private int id;
	private String name;
	private int score;

	public Object clone() {
		Student std = new Student();

		std.id = this.id;
		std.name = this.name;
		std.score = this.score;

		return std;
	}
}




/*=================================================

#	----- 原型 の 小结 ----- 


1. 原型模式是根据一个现有对象实例复制出一个新的实例，复制出的类型和属性与原实例相同。

模版: 
    Collections.copyOf(Instance, Instance.length);
	实例:
		Arrays.copyOf(array, array.length);
	



*/

